#![allow(dead_code)]
#![allow(unused_variables)]

use crate::cmd::flag::parse;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
use std::thread;

pub trait ExecCmdTrait {
    fn run(
        &mut self,
        _args: HashMap<String, String>,
        _cmdtree: &parse::FlagTree,
    ) -> Result<(), String> {
        Ok(())
    }
}

//有参数的初始化函数
impl<F> ExecCmdTrait for F
where
    F: Fn(HashMap<String, String>, &parse::FlagTree) -> Result<(), String>,
{
    fn run(
        &mut self,
        args: HashMap<String, String>,
        cmdtree: &parse::FlagTree,
    ) -> Result<(), String> {
        self(args, cmdtree)
    }
}

pub struct Exec {
    flags: parse::FlagTree,
    default: Box<dyn ExecCmdTrait>,
    exit: Arc<Mutex<dyn ExecCmdTrait>>,
    cmds: HashMap<String, Box<dyn ExecCmdTrait>>,
    run_end: Option<Sender<bool>>,
}

fn default_run(_: HashMap<String, String>, _: &parse::FlagTree) -> Result<(), String> {
    Ok(())
}
async fn default_exit_lister<F>(
    args: HashMap<String, String>,
    flag: parse::FlagTree,
    mut function: F,
) where
    F: Fn(HashMap<String, String>, &parse::FlagTree) -> Result<(), String>,
{
    let term = Arc::new(AtomicBool::new(false));
    signal_hook::flag::register(signal_hook::SIGTERM, Arc::clone(&term))
        .expect("系统信号SIGTERM(15) 监听失败");
    signal_hook::flag::register(signal_hook::SIGINT, Arc::clone(&term))
        .expect("系统信号SIGINT(2) 监听失败");
    while !term.load(Ordering::Relaxed) {
        // TODO
        thread::sleep(std::time::Duration::from_secs(1));
    }
    function.run(args, &flag).unwrap();
    std::process::exit(1)
}
pub fn default_exit(
    args: HashMap<String, String>,
    cmdtree: &parse::FlagTree,
) -> Result<(), String> {
    println!("{} ->任务结束", cmdtree.name);
    Ok(())
}

impl Exec {
    pub fn new() -> Self {
        let f = parse::load().expect("输入参数解析错误");
        Exec {
            flags: f,
            default: Box::new(default_run),
            exit: Arc::new(Mutex::new(default_exit)),
            cmds: HashMap::new(),
            run_end: None,
        }
    }
    pub fn default<T: ExecCmdTrait + 'static>(mut self, d: T) -> Self {
        self.default = Box::new(d);
        self
    }
    pub fn exit<T>(mut self, d: T) -> Self
    where
        T: Fn(HashMap<String, String>, &parse::FlagTree) -> Result<(), String> + Send + 'static,
    {
        let mut args = HashMap::new();
        for i in self.flags.global.iter() {
            args.insert(i.1.key.clone(), i.1.value.clone());
        }
        let f = Arc::new(Mutex::new(d));
        let flags = self.flags.clone();
        let (sx, rx) = channel();
        self.run_end = Some(sx);
        tokio::spawn(async move {
            let term = Arc::new(AtomicBool::new(false));
            signal_hook::flag::register(signal_hook::SIGTERM, Arc::clone(&term))
                .expect("系统信号SIGTERM(15) 监听失败");
            signal_hook::flag::register(signal_hook::SIGINT, Arc::clone(&term))
                .expect("系统信号SIGINT(2) 监听失败");
            while !term.load(Ordering::Relaxed) {
                if rx.try_recv().is_ok() {
                    break;
                }
                thread::sleep(std::time::Duration::from_secs(1));
            }
            let f = f.lock().unwrap();
            f(args.clone(), &flags).unwrap();
            std::process::exit(1);
        });
        // tokio::spawn(default_exit_lister(args.clone(), self.flags.clone(),  default_exit));
        self
    }
    pub fn registered<T: ExecCmdTrait + 'static>(mut self, cmd: &str, r: T) -> Self {
        self.cmds.insert(cmd.to_string(), Box::new(r));
        self
    }
    pub fn run(mut self) -> Result<(), String> {
        let mut args = HashMap::new();
        for i in self.flags.global.iter() {
            args.insert(i.1.key.clone(), i.1.value.clone());
        }
        if let Err(e) = self.default.run(args.clone(), &self.flags) {
            return Err(e);
        };
        for (cmd, flag) in self.flags.flags.iter() {
            let flag_cmd = match self.cmds.get_mut(cmd.as_str()) {
                None => {
                    return Err(
                        (format!("命令:{} 未找到对应的可执行方法", cmd.as_str())).to_string()
                    );
                }
                Some(s) => s,
            };
            let mut child_args = args.clone();
            if let Some(child_flag) = &flag.chile_flags {
                for item in child_flag {
                    child_args.insert(item.key.clone(), item.value.clone());
                }
            }
            if let Err(e) = flag_cmd.run(child_args, &self.flags) {
                return Err(e);
            }
        }
        if let Some(chan) = self.run_end {
            chan.send(true).unwrap();
        }
        Ok(())
    }
}
